//
//  Coder.swift
//  MoonKit
//
//  Created by moon on 2019/3/1.
//  Copyright © 2019 moon. All rights reserved.
//

import Foundation

public enum CodingOperation {
	case encode
	case decode
}

public protocol Coder : class {
	var codingOperation:CodingOperation { get } //编码还是解码
	var codingPath: [CodingKey] { get set }	//要编解码的数据的路径列表
	var userInfo: [CodingUserInfoKey : Any] { get }//扩展用
	var nilPresent: Bool { get set }//使用.=编解码时,是否编解码nil
	
	func container<Key>(keyedBy type: Key.Type) throws -> KeyedCodingContainer<Key> where Key : CodingKey
	func unkeyedContainer() throws -> UnkeyedCodingContainer
	func singleValueContainer() throws -> SingleValueCodingContainer
}

public struct StringCodingKey : CodingKey {
	public var stringValue: String
	public init(_ stringValue: String){
		self.stringValue = stringValue
	}
	public init(_ codingKey:CodingKey){
		self.intValue = codingKey.intValue
		self.stringValue = codingKey.stringValue
	}
	public init(stringValue: String){
		self.stringValue = stringValue
	}
	public init(stringValue: String,convertIntValue:Bool) {
		if convertIntValue , let intValue = Int(stringValue) {
			self.init(intValue: intValue)
		} else {
			self.init(stringValue)
		}
	}
	public var intValue: Int?
	public init(intValue: Int){
		self.intValue = intValue
		self.stringValue = "\(intValue)"
	}
}
extension Coder {
	public var isEncoding:Bool {
		return codingOperation == .encode
	}
	public var isDecoding:Bool {
		return codingOperation == .decode
	}
}
extension Coder {
	
	/// 设置codingPath数组.用于链式调用
	/// 会同时设置nilPresent=false
	///
	/// - Parameter codingPath: 当前要操作的codingPath数组
	/// - Returns: 自身
	public subscript(codingPath: [CodingKey]) -> Coder {
		self.codingPath = codingPath
		self.nilPresent = false
		return self
	}
	
	/// 设置codingPath数组.用于链式调用
	/// 会同时设置nilPresent=false
	///
	/// - Parameter codingPath: 当前要操作的codingPath
	/// - Returns: 自身
	public subscript(codingPath: CodingKey) -> Coder {
		return self[[codingPath]]
	}
//	
//	/// 设置codingPath数组.用于链式调用
//	/// 会同时设置nilPresent=false
//	/// 对codingPath字符串,会进行解析,以"."为分隔符,进行分割.分割的部分,如果为数字,则将转换为含有intValue的CodingPath.
//	///
//	/// - Parameter codingPath: 当前要操作的codingPath字符串
//	/// - Returns: 自身
//	public subscript(codingPath: String) -> Coder {
//		return self[codingPath,true,"."]
//	}
	
	/// 设置codingPath数组.用于链式调用
	/// 会同时设置nilPresent=false
	/// 当nested=true时,会对codingPath字符串,会进行解析,以delimiter参数为分隔符,进行分割.分割的部分,如果为数字,则将转换为含有intValue的CodingPath.
	///
	/// - Parameters:
	///   - codingPath: 当前要操作的codingPath字符串
	///   - nested: codingPath字符串是否需要进行分割处理
	///   - delimiter: 当nested=true时,以该字符串对codingPath进行分割处理
	/// - Returns: 自身
	public subscript(codingPath: String, nested: Bool = true, delimiter: String = ".") -> Coder {
		if nested {
			return self[codingPath.components(separatedBy: delimiter).filter{!$0.isEmpty}.map{StringCodingKey(stringValue: $0, convertIntValue: nested)}]
		} else {
			return self[StringCodingKey(codingPath)]
		}
	}
	
	/// 设置codingPath数组.用于链式调用
	/// 会同时设置nilPresent=false
	///
	/// - Parameter codingPath: 数组索引的codingPath
	/// - Returns: 自身
	public subscript(codingPath: Int) -> Coder {
		return self[StringCodingKey(intValue: codingPath)]
	}
	
	/// 设置自身的nilPresent参数.用于链式调用
	///
	/// - Parameter nilPresent: 设置自身的nilPresent参数
	/// - Returns: 自身
	public subscript(nilPresent :Bool) -> Coder {
		self.nilPresent = nilPresent
		return self
	}
}
extension Coder {
	/// 解码当前codingPath对应的值是否为nil
	///
	/// - Returns: 当前codingPath对应的值是否为nil
	/// - Throws: `CodingError.invalidOperation`:当前操作不为解码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.keyNotFound`: codingPath对应的key不存在
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func decodeNil() throws -> Bool {
		guard isDecoding else { throw CodingError.invalidOperation }
		return try decodeNil(codingPath)
	}
    
    /// 解码当前codingPath对应的值是否为nil
    ///
    /// - Returns: 当前codingPath对应的值是否为nil
    public func decodeNilValue() -> Bool {
        if let value = try? self.decodeNil() {
            return value
        }
        return false
    }
	
	/// 解码当前codingPath对应的值
	///	如果codingPath的值解码为nil时或者codingPath不存在时,将返回nil,其余情况返回对象出来
	///
	/// - Returns: 指定的类型的对象
	/// - Throws: `CodingError.invalidOperation`:当前操作不为解码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func decode<T>() throws -> T? where T:Codable{
		guard isDecoding else { throw CodingError.invalidOperation }
		return try decodeIfPresent(T.self, codingPath)
	}
    
    /// 解码当前codingPath对应的值
    /// 如果codingPath的值解码为nil时或者codingPath不存在时,将返回nil,其余情况返回对象出来
    /// - Returns: 指定的类型的对象
    public func decodeValue<T>() -> T? where T:Codable{
        var value:T?
        do {
            value = try self.decode()
        } catch let error as CodingError {
            error.printError()
        } catch {
            print("error:\(error)")
        }
        return value
    }
    
	/// 解码当前codingPath对应的值
	/// - Returns: 指定的类型的对象
	///
	/// - Throws: `CodingError.invalidOperation`:当前操作不为解码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.valueNotFound`: 解码出null
	/// - Throws: `CodingError.keyNotFound`: key不存在
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func decode<T>() throws -> T where T:Codable{
		guard isDecoding else { throw CodingError.invalidOperation }
		return try decode(T.self, codingPath)
	}
    public func decode<T>(to value:inout T) throws where T:Codable {
        guard isDecoding else { throw CodingError.invalidOperation }
        try decode(codingPath, to: &value)
    }
	/// 解码当前codingPath对应的值为Keyed容器
	/// - Returns: keyed容器
	///
	/// - Throws: `CodingError.invalidOperation`:当前操作不为解码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.valueNotFound`: 解码出null
	/// - Throws: `CodingError.keyNotFound`: key不存在
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func decode<Key>() throws -> KeyedCodingContainer<Key> where Key:CodingKey{
		if codingPath.isEmpty {
			return try self.container(keyedBy: Key.self)
		} else {
            var codingPaths = codingPath
            do {
                var (singleValueContainer,unkeyedContainer,container) = try self._currentContainer(codingPaths)
                if singleValueContainer != nil {
                    throw CodingError._typeMismatch(at: [], expectation: KeyedCodingContainer<StringCodingKey>.self, reality: singleValueContainer!)
                } else if unkeyedContainer != nil {
                    unkeyedContainer!.currentIndex = codingPaths.removeLast().intValue!
                    return try unkeyedContainer!.nestedContainer(keyedBy: Key.self)
                } else {
                    return try container!.nestedContainer(keyedBy: Key.self, forKey: StringCodingKey(codingPaths.removeLast()))
                }
            } catch let originError as CodingError {
                let error = CodingError(preCodingPath: codingPaths, current: originError)
                throw error
            } catch {
                throw error
            }
		}
	}
	
	/// 解码当前codingPath对应的值为unkeyed容器
	/// - Returns: unkeyed容器
	///
	/// - Throws: `CodingError.invalidOperation`:当前操作不为解码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.valueNotFound`: 解码出null
	/// - Throws: `CodingError.keyNotFound`: key不存在
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func decode() throws -> UnkeyedCodingContainer {
		if codingPath.isEmpty {
			return try self.unkeyedContainer()
		} else {
            var codingPaths = codingPath
            do {
                var (singleValueContainer,unkeyedContainer,container) = try self._currentContainer(codingPaths)
                if singleValueContainer != nil {
                    throw CodingError._typeMismatch(at: [], expectation: UnkeyedCodingContainer.self, reality: singleValueContainer!)
                } else if unkeyedContainer != nil {
                    unkeyedContainer!.currentIndex = codingPaths.removeLast().intValue!
                    return try unkeyedContainer!.nestedUnkeyedContainer()
                } else {
                    return try container!.nestedUnkeyedContainer(forKey: StringCodingKey(codingPaths.removeLast()))
                }
            } catch let originError as CodingError {
                let error = CodingError(preCodingPath: codingPaths, current: originError)
                throw error
            } catch {
                throw error
            }
		}
	}
	
	/// 解码当前codingPath对应的值为singlevalue容器
	/// - Returns: singlevalue容器
	///
	/// - Throws: `CodingError.invalidOperation`:当前操作不为解码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.valueNotFound`: 解码出null
	/// - Throws: `CodingError.keyNotFound`: key不存在
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func decode() throws -> SingleValueCodingContainer {
        let codingPaths = codingPath
        do {
//            let coder = try getCoder(codingPaths)
//            try coder.singleValueContainer()
            let (singleValueContainer,unkeyedContainer,container) = try self._currentContainer(codingPaths)
            if singleValueContainer != nil {
                return singleValueContainer!
            } else if unkeyedContainer != nil {
                throw CodingError._typeMismatch(at: [], expectation: SingleValueCodingContainer.self, reality: unkeyedContainer!)
            } else {
                throw CodingError._typeMismatch(at: [], expectation: SingleValueCodingContainer.self, reality: container!)
            }
        } catch let originError as CodingError {
            let error = CodingError(preCodingPath: codingPaths, current: originError)
            throw error
        } catch {
            throw error
        }
	}
	
	/// 解码当前codingPath对应的值为新的Coder容器
	/// - Returns: Coder容器
	///
	/// - Throws: `CodingError.invalidOperation`:当前操作不为解码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.valueNotFound`: 解码出null
	/// - Throws: `CodingError.keyNotFound`: key不存在
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
    public func decode() throws -> Coder {
        let coder:Coder = try getCoder(codingPath)
        return coder
	}
    public func getCoder() throws -> Coder {
        let coder:Coder = try getCoder(codingPath)
        return coder
    }
	/// 编码nil到当前codingPath
	///
	/// - Throws: `CodingError.invalidOperation`:当前操作不为编码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func encodeNil() throws {
		guard isEncoding else { throw CodingError.invalidOperation }
		try encodeNil(codingPath)
	}
	
	/// 编码值到当前codingPath
	///
	/// - Parameter value: 待编码的值
	/// - Throws: `CodingError.invalidOperation`:当前操作不为编码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func encode<T>(_ value:T) throws where T:Codable {
		guard isEncoding else { throw CodingError.invalidOperation }
		try encode(value, codingPath)
	}

	/// 编码一系列值到当前codingPath
	///
	/// - Parameter sequence: 待编码的值序列
	/// - Throws: `CodingError.invalidOperation`:当前操作不为编码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func encode<T>(contentsOf sequence: T ) throws where T : Sequence, T.Element : Codable {
		guard isEncoding else { throw CodingError.invalidOperation }
		try encode(contentsOf: sequence, codingPath)
	}
}


extension Coder {
	fileprivate func _currentContainer(_ codingPath: [CodingKey]) throws -> (SingleValueCodingContainer?,UnkeyedCodingContainer?,KeyedCodingContainer<StringCodingKey>?) {
		if codingPath.isEmpty {
			let c = try self.singleValueContainer()
			return (c,nil,nil)
		}
		var key:CodingKey?
		var container:KeyedCodingContainer<StringCodingKey>?
		var unkeyContainer:UnkeyedCodingContainer?
		if codingPath.count == 1 {
			key = codingPath.first!
			if let _ = key!.intValue {
				unkeyContainer = try self.unkeyedContainer()
			} else {
				container = try self.container(keyedBy: StringCodingKey.self)
			}
		} else {
			for (i,k) in codingPath[0 ..< codingPath.count].enumerated() {
				if i == 0 {
					if let _ = k.intValue {
						unkeyContainer = try self.unkeyedContainer()
					} else {
						container = try self.container(keyedBy: StringCodingKey.self)
					}
				}
				if i < codingPath.count-1 {
					let k2 = codingPath[i+1]
					if let index = k.intValue {
						unkeyContainer!.currentIndex = index
						if let _ = k2.intValue {
							unkeyContainer = try unkeyContainer!.nestedUnkeyedContainer()
						} else {
							container = try unkeyContainer!.nestedContainer(keyedBy: StringCodingKey.self)
						}
					} else {
						if let _ = k2.intValue {
							unkeyContainer = try container!.nestedUnkeyedContainer(forKey: StringCodingKey(k))
						} else {
							container = try container!.nestedContainer(keyedBy: StringCodingKey.self, forKey: StringCodingKey(k))
						}
					}
				}
			}
			key = codingPath.last!
		}
		return (nil,unkeyContainer,container)
	}
	
    public func getCoder(_ codingPath:[CodingKey]) throws -> Coder {
        guard !codingPath.isEmpty else {
            return self
        }
        var codingPaths = codingPath
        do {
            var (singleValueContainer,unkeyedContainer,container) = try self._currentContainer(codingPaths)
            if singleValueContainer != nil {
                return try singleValueContainer!.superCoder()
            } else if unkeyedContainer != nil {
                unkeyedContainer!.currentIndex = codingPaths.removeLast().intValue!
                return try unkeyedContainer!.superCoder()
            } else {
                return try container!.superCoder(forKey: StringCodingKey(codingPaths.removeLast()))
            }
        } catch let originError as CodingError {
            let error = CodingError(preCodingPath: codingPaths, current: originError)
            throw error
        } catch {
            throw error
        }
    }
    
	/// 解码指定codingPath对应的值是否为nil
	///
	/// - Parameters:
	///   - codingPath: 指定的codingPath
	/// - Returns: 当前codingPath对应的值是否为nil
	/// - Throws: `CodingError.invalidOperation`:当前操作不为解码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.keyNotFound`: codingPath对应的key不存在
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func decodeNil(_ codingPath:[CodingKey]) throws -> Bool {
        var codingPaths = codingPath
        do {
            let coder = try getCoder(codingPaths)
            if let singleValueContainer:SingleValueCodingContainer = try? coder.singleValueContainer() {
                return singleValueContainer.decodeNil()
            } else if var unkeyedContainer:UnkeyedCodingContainer = try? coder.unkeyedContainer() {
                unkeyedContainer.currentIndex = codingPaths.removeLast().intValue!
                return try unkeyedContainer.decodeNil()
            } else{
                var container:KeyedCodingContainer<StringCodingKey> = try coder.container(keyedBy: StringCodingKey.self)
                return try container.decodeNil(forKey: StringCodingKey(codingPaths.removeLast()))
            }
        } catch let originError as CodingError {
            let error = CodingError(preCodingPath: codingPaths, current: originError)
            throw error
        } catch {
            throw error
        }
	}
	
    /// 解码指定codingPath对应的值
    ///    如果codingPath的值解码为nil时,或者codingPath不存在时,将返回nil,其余情况返回对象出来
    ///
    /// - Parameters:
    ///   - type: 解码结果类型
    ///   - codingPath: 指定的codingPath
    /// - Returns: 指定的类型的对象
    /// - Throws: `CodingError.invalidOperation`:当前操作不为解码
    /// - Throws: `CodingError.typeMismatch`: 类型错误
    /// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
    public func decodeIfPresent<T>(_ type: T.Type, _ codingPath:[CodingKey] ) throws -> T? where T : Codable {
        var codingPaths = codingPath
        do {
            let coder = try getCoder(codingPaths)
            if let singleValueContainer:SingleValueCodingContainer = try? coder.singleValueContainer() {
                return try singleValueContainer.decodeCodableValueIfPresent(type)
            } else if var unkeyedContainer:UnkeyedCodingContainer = try? coder.unkeyedContainer() {
                unkeyedContainer.currentIndex = codingPaths.removeLast().intValue!
                return try unkeyedContainer.decodeCodableValueIfPresent(type)
            } else{
                var container:KeyedCodingContainer<StringCodingKey> = try coder.container(keyedBy: StringCodingKey.self)
                return try container.decodeCodableValueIfPresent(type, forKey: StringCodingKey(codingPaths.removeLast()))
            }
        } catch let originError as CodingError {
            let error = CodingError(preCodingPath: codingPaths, current: originError)
            throw error
        } catch {
            throw error
        }
    }
    
	/// 解码指定codingPath对应的值
	///
	/// - Parameters:
	///   - type: 解码结果类型
	///   - codingPath: 指定的codingPath
	/// - Returns: 指定的类型的对象
	/// - Throws: `CodingError.invalidOperation`:当前操作不为解码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.valueNotFound`: 解码出null
	/// - Throws: `CodingError.keyNotFound`: key不存在
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func decode<T>(_ type: T.Type, _ codingPath:[CodingKey]) throws -> T where T : Codable {
        var codingPaths = codingPath
        do {
            let coder = try getCoder(codingPaths)
            if let singleValueContainer:SingleValueCodingContainer = try? coder.singleValueContainer() {
                return try singleValueContainer.decodeCodableValue(type)
            } else if var unkeyedContainer:UnkeyedCodingContainer = try? coder.unkeyedContainer() {
                unkeyedContainer.currentIndex = codingPaths.removeLast().intValue!
                return try unkeyedContainer.decodeCodableValue(type)
            } else{
                var container:KeyedCodingContainer<StringCodingKey> = try coder.container(keyedBy: StringCodingKey.self)
                return try container.decodeCodableValue(type, forKey: StringCodingKey(codingPaths.removeLast()))
            }
        } catch let originError as CodingError{
            let error = CodingError(preCodingPath: codingPaths, current: originError)
            throw error
        } catch {
            throw error
        }
	}
    public func decode<T>(_ codingPath:[CodingKey],to value:inout T) throws where T : Codable {
        let codingPaths = codingPath
        do {
            let coder:Coder = try self.getCoder(codingPaths)
            try value.code(coder: coder)
        } catch let originError as CodingError{
            let error = CodingError(preCodingPath: codingPaths, current: originError)
            throw error
        } catch {
            throw error
        }
    }
	
	/// 编码nil到指定的codingPath
	///
	/// - Parameters:
	///   - codingPath: 指定的codingPath
	/// - Throws: `CodingError.invalidOperation`:当前操作不为编码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func encodeNil(_ codingPath:[CodingKey]) throws {
        var codingPaths = codingPath
        do {
            let coder = try getCoder(codingPaths)
            if var singleValueContainer:SingleValueCodingContainer = try? coder.singleValueContainer() {
                try singleValueContainer.encodeNil()
            } else if var unkeyedContainer:UnkeyedCodingContainer = try? coder.unkeyedContainer() {
                unkeyedContainer.currentIndex = codingPaths.removeLast().intValue!
                try unkeyedContainer.encodeNil()
            } else{
                var container:KeyedCodingContainer<StringCodingKey> = try coder.container(keyedBy: StringCodingKey.self)
                try container.encodeNil(forKey: StringCodingKey(codingPaths.removeLast()))
            }
        } catch let originError as CodingError {
            let error = CodingError(preCodingPath: codingPaths, current: originError)
            throw error
        } catch {
            throw error
        }
	}
	
	/// 编码值到指定的codingPath
	///
	/// - Parameters:
	///   - value: 待编码的值
	///   - codingPath: 指定的codingPath
	/// - Throws: `CodingError.invalidOperation`:当前操作不为编码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func encode<T>(_ value: T, _ codingPath: [CodingKey]) throws where T : Codable {
        var codingPaths = codingPath
        do {
            let coder = try getCoder(codingPaths)
            if var singleValueContainer:SingleValueCodingContainer = try? coder.singleValueContainer() {
                try singleValueContainer.encodeCodableValue(value)
            } else if var unkeyedContainer:UnkeyedCodingContainer = try? coder.unkeyedContainer() {
                unkeyedContainer.currentIndex = codingPaths.removeLast().intValue!
                try unkeyedContainer.encodeCodableValue(value)
            } else{
                var container:KeyedCodingContainer<StringCodingKey> = try coder.container(keyedBy: StringCodingKey.self)
                try container.encodeCodableValue(value, forKey: StringCodingKey(codingPaths.removeLast()))
            }
        } catch let originError as CodingError {
            let error = CodingError(preCodingPath: codingPaths, current: originError)
            throw error
        } catch {
            throw error
        }
	}
	
	/// 编码一系列值到指定codingPath
	///
	/// - Parameters:
	///   - sequence: 待编码的值序列
	///   - codingPath: 指定的codingPath
	/// - Throws: `CodingError.invalidOperation`:当前操作不为编码
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
	public func encode<T>(contentsOf sequence: T, _ codingPath:[CodingKey]) throws where T : Sequence, T.Element : Codable {
        let codingPaths = codingPath
        do {
            let coder = try getCoder(codingPaths)
            var unkeyedContainer:UnkeyedCodingContainer = try coder.unkeyedContainer()
            for var element in sequence {
                let unkeyedCoder:Coder = try unkeyedContainer.superCoder()
                try element.code(coder: unkeyedCoder)
            }
        } catch let originError as CodingError {
            let error = CodingError(preCodingPath: codingPaths, current: originError)
            throw error
        } catch {
            throw error
        }
	}
	
}

extension Coder {
    public func decode<T,C>(convertor:C) throws -> T? where T:Codable,C:CodingConvertor,C.CodingType==T {
        guard isDecoding else { throw CodingError.invalidOperation }
        let coder = try self.getCoder(codingPath)
        return try convertor.decodeIfPresent(from: coder)
    }
    public func decodeValue<T,C>(convertor:C) -> T? where T:Codable,C:CodingConvertor,C.CodingType==T {
        var value:T?
        do {
            value = try self.decode(convertor: convertor)
        } catch let error as CodingError{
            error.printError()
        } catch {
            print("error:\(error)")
        }
        return value
    }
    public func decode<T,C>(convertor:C) throws -> T where T:Codable,C:CodingConvertor,C.CodingType==T {
        guard isDecoding else { throw CodingError.invalidOperation }
        let coder = try self.getCoder(codingPath)
        return try convertor.decode(from: coder)
    }
    
    /// 使用编码器进行编码
    ///
    /// - Parameters:
    ///   - value: 待操作值
    ///   - convertor: 编码器
    /// - Throws: `CodingError.invalidOperation`:当前操作不为编码
    /// - Throws: `CodingError.typeMismatch`: 类型错误
    /// - Throws: `CodingError.indexOutOfRange` : codingPath中的索引超过范围
    /// - Throws: `CodingError.convertFail` : 编码器错误
    public func encode<T,C>(_ value:T, convertor:C) throws where T:Codable,C:CodingConvertor,C.CodingType==T {
        guard isEncoding else { throw CodingError.invalidOperation }
        let coder = try self.getCoder(codingPath)
        try convertor.encode(to: coder, value: value)
    }
}
